import type { AxiosError, AxiosInstance, AxiosResponse, InternalAxiosRequestConfig } from "axios";
import { AxiosCanceler } from "@/api/helper/axiosCancel";
import { ResultEnum } from "@/enums/httpEnum";
import { checkStatus } from "@/api/helper/checkStatus";
import { useNotify } from "nutui-uniapp/components/notify/use-notify";
import { useUserStore } from "@/stores/modules/userStore";

const notify = useNotify();
const axiosCanceler = new AxiosCanceler();
export interface CustomAxiosRequestConfig extends InternalAxiosRequestConfig {
  // loading?: boolean;
  cancel?: boolean;
}

export function setupInterceptors(instance: AxiosInstance) {
  /**
   * @description 请求拦截器
   * 客户端发送请求 -> [请求拦截器] -> 服务器
   * token校验(JWT) : 接受服务器返回的 token,存储到 vuex/pinia/本地储存当中
   */
  instance.interceptors.request.use(
    (config: CustomAxiosRequestConfig) => {
      const userStore = useUserStore();
      // 重复请求不需要取消，在 api 服务中通过指定的第三个参数: { cancel: false } 来控制
      config.cancel ??= true;
      // eslint-disable-next-line @typescript-eslint/no-unused-expressions
      config.cancel && axiosCanceler.addPending(config);
      // config.loading ??= true;
      // config.loading && showFullScreenLoading();
      if (config.headers && typeof config.headers.set === "function") {
        config.headers.set("x-access-token", userStore.token);
      }
      return config;
    },
    (error: AxiosError) => {
      return Promise.reject(error);
    },
  );

  /**
   * @description 响应拦截器
   *  服务器换返回信息 -> [拦截统一处理] -> 客户端JS获取到信息
   */
  instance.interceptors.response.use(
    (response: AxiosResponse & { config: CustomAxiosRequestConfig }) => {
      const { data, config } = response;
      const userStore = useUserStore();
      axiosCanceler.removePending(config);

      // config.loading && tryHideFullScreenLoading();
      // 登录失效
      if (data.code == ResultEnum.OVERDUE) {
        userStore.setToken("");
        uni.navigateTo({ url: "/pages/login/index" });
        notify.danger(data.msg);
        return Promise.reject(data);
      }
      // 全局错误信息拦截（防止下载文件的时候返回数据流，没有 code 直接报错）
      if (data.code && data.code !== ResultEnum.SUCCESS) {
        notify.danger(data.msg);
        return Promise.reject(data);
      }
      // 成功请求（在页面上除非特殊情况，否则不用处理失败逻辑）
      return data;
    },
    async (error: AxiosError) => {
      // tryHideFullScreenLoading();
      const { response } = error;
      // 请求超时 && 网络错误单独判断，没有 response
      if (error.message.indexOf("timeout") !== -1) notify.danger("请求超时！请您稍后重试");
      if (error.message.indexOf("Network Error") !== -1) notify.danger("网络错误！请您稍后重试");
      // 根据服务器响应的错误状态码，做不同的处理
      if (response) checkStatus(response.status);
      // 服务器结果都没有返回(可能服务器错误可能客户端断网)，断网处理:可以跳转到断网页面
      if (!window.navigator.onLine) uni.navigateTo({ url: "/pages/error/500/index" });
      return Promise.reject(error);
    },
  );
}
